package com.neu.yth.nepBackend.gateway.filter.globalfilter;

import cn.hutool.jwt.JWTUtil;
import com.alibaba.fastjson.JSON;
import com.neu.yth.nepBackend.enums.ResponseEnum;
import com.neu.yth.nepBackend.gateway.config.AuthProperties;
import com.neu.yth.nepBackend.redis.config.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @ClassName MyGlobalFilter
 * @Description
 * @Author YTH
 * @Date 2024-07-11 18:29
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private final AuthProperties authProperties;

    @Autowired
    private RedisUtil redisUtil;

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("MyGlobalFilter:权限认证过滤器");
        //获取request
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        byte[] bits = null;
        //判断是否需要做登录拦截
        if (isExclude(request.getPath().toString())) {
            //放行
            return chain.filter(exchange);
        }

        //获取token
        List<String> headers = request.getHeaders().get("Authorization");
        String token = null;
        String userId = null;
        if (headers != null && !headers.isEmpty()) {
            token = headers.get(0);
        }
        headers = request.getHeaders().get("UserID");
        if (headers != null && !headers.isEmpty()) {
            userId = headers.get(0);
        }

        //校验解析token
        try {
            log.info("token:{}", token);
            log.info("userId:{}", userId);
            String redisToken = (String) redisUtil.get(userId + "-token");
            String msg = "";
            if (token == null) {
                // token无效，准备返回错误响应
                msg = "未从Header中获取到Token";
            } else if (redisToken == null) {
                // token无效，准备返回错误响应
                msg = "未从Redis中获取到Token";
            } else if (!redisToken.equals(token)) {
                // token无效，准备返回错误响应
                msg = "Token无效";
            } else {
                log.info("token验证成功");
                return chain.filter(exchange);
            }
            log.error(msg);
            bits = ("{\"code\": " + 315 + ",\n" +
                    "\"msg\": \"" + msg + "\",\n" +
                    "\t\"result\":null \n" + "\n}"
            ).getBytes(StandardCharsets.UTF_8);
            DataBuffer buffer = response.bufferFactory().wrap(bits);
            response.setStatusCode(HttpStatus.OK);
            //指定编码，否则在浏览器中会中文乱码
            response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));
        } catch (Exception e) { //token无效
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }


    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    private boolean isExclude(String path) {
        for (String excludePath : authProperties.getExcludePaths()) {
            if (antPathMatcher.match(excludePath, path)) {
                return true;
            }
        }
        return false;
    }
}

